<?php
/**
 * 工厂方法
 * 一个工厂返回一个产品
 * */

/**
 * 再看工厂方法:
 *          一个工厂实例化一个类 , 一个工厂生产一个对象
 *
 *  1. 工厂方法相当于一个虚拟构造器, 用来专门处理该类的生产 , 通过该构造器来构造一个对应的产品对象
 *  2. 有什么好处 ?
 *
 *
 *  好处:
 *  1. 将实例化的职责划分到工厂类, 客户端更加专注自己的业务 , 而不不要承担该对象的创建职责
 *  2. 客户端只需依赖一个抽象工厂 , 所谓依赖稳定 , 即使是发生错误, 我们也无需修改客户端代码
 *     而是直接新建一个工厂替换上去即可 , 替换过程可以考虑 反射 / 配置读取
 *
 *
 *
 *  每个产品都需要一个对应的工厂来创建 , 其实就是为每个类添加了一个外部的构造器 , 将变化的部分规避到了构造器
 *  而不需要客户端来承担 , 而这个构造器都是实现了统一的接口 , 可以灵活地扩展
 * */


class Config{
    /**
     * 从配置读取当前驱动
     * */
    public static function getLogFactory(){
        return 'FactoryLogDataBase';
    }
}

# 抽象日志类
abstract class Log{
    /**
     * @param $info
     * @param $data
     */
    abstract public function write($info,$data);

    /**
     * 日志快速写入方法
     * @param $info
     * @param $data
     */
    final public static function writeFast($info,$data){
        $driver = Config::getLogFactory();

        /**
         * @var FactoryLog $factory
         * */
        $factory = new $driver;
        /**
         * @var Log $log
         * */
        $log = $factory->getLog();
        $log->write($info,$data);
    }
}


class LogFile extends Log {

    /**
     * @inheritDoc
     */
    public function write($info, $data)
    {
        echo "文件写入:[$info]$data";
    }
}

class LogDataBase extends Log {

    /**
     * @inheritDoc
     */
    public function write($info, $data)
    {
        echo "数据库写入:[$info]$data";
    }
}


abstract class FactoryLog{
    /**
     * @return Log
     * */
    abstract public function getLog();
}

class FactoryLogFile extends FactoryLog{

    public function getLog()
    {
        // 创建前可以对环境进行判断 , 是否支持文件写入
        // 注入文件写入驱动
        return new LogFile();
    }
}

class FactoryLogDataBase extends FactoryLog{
    public function getLog()
    {
        // 创建前可以判断是否支持数据库
        // 注入数据库操作模型
        return new LogDataBase();
    }
}

/**
 * 具体实例化 根据 配置来
 * 这样有什么好处 ?
 * 假如: 某天我们需要更换 日志的驱动 , 我们直接修改配置即可, 而不用 一个一个去修改
 *       LogFile::class => LogDataBase::class
 * */

//$factory = new FactoryLogDataBase();
//$log = $factory->getLog();
//$log->write('错误','今日短信发送数量已达上限!');

Log::writeFast('警告','当前系统内存不足,无法运行!');

